home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Deutsche Edition 1
/
Deutsche Edition 1.iso
/
amok
/
051-060
/
amok58
/
realconversions2
/
realconversions2.mod
< prev
next >
Wrap
Text File
|
1993-11-04
|
6KB
|
257 lines
(**********************************************************************
:Program. (Long)RealConversions2
:Contents. Procedures for converting strings to reals and vice versa
:Author. Stefan Salewski
:Address. Stefan Salewski, Stolper Weg 3, D-2160 Stade
:Copyright. FD
:Language. Oberon
:Translator. Amiga-Oberon-Compiler V2.0
:History. V1.0 18-08-91
:Remark. Replacement of the original REAL- and LONGREAL-Conversions
:Remark. This module if more accurate
:Remark. To get the version for LONGREALs, type in CLI:
:Remark. Oberon SET LONGREAL RealConversion2
**********************************************************************)
(* $IF LONGREAL *)
MODULE LongRealConversions2;
IMPORT MathLib0:MathIEEEDoubBas;
TYPE Real=LONGREAL;
CONST ExpSize=5; (* Strings.Length('-E007') *)
TenE18 =1.0D18;
(* $ELSE *)
MODULE RealConversions2;
IMPORT MathLib0:MathFFP;
TYPE Real=REAL;
CONST ExpSize=4; (* Strings.Length('-E07') *)
TenE18 =1.0E18;
(* $END *)
CONST
Digit='0123456789';
MaxReal=MAX(Real);
MinReal=MIN(Real);
Plus= '+';
Minus='-';
Space=' ';
Point='.';
Exponent='E';
Nul=0X;
TenE6 =1000000;
TenE8 =100000000;
PROCEDURE Pow10(n:INTEGER):Real;
(* Only for n>=0; RETURNS 10^n *)
VAR
x:Real;
BEGIN
IF n<0 THEN HALT(0) END;
x:=1;
WHILE n>0 DO
IF n>=18 THEN
x:=x*TenE18;
DEC(n,18)
ELSIF n>=6 THEN
x:=x*TenE6;
DEC(n,6)
ELSE
x:=x*10;
DEC(n)
END;
END;
RETURN x
END Pow10;
PROCEDURE Norm(VAR x:Real; VAR n:INTEGER);
(* Only for x>=0 ; RETURNS 1 <= x <10 (or zero if x=0 ) *)
BEGIN
n:=0;
IF x=0 THEN RETURN END;
WHILE x< (1/TenE18) DO x:=x*TenE18; DEC(n,18) END;
WHILE x>= TenE18 DO x:=x/TenE18; INC(n,18) END;
WHILE x< (1/TenE6) DO x:=x*TenE6; DEC(n,6) END;
WHILE x>= TenE6 DO x:=x/TenE6; INC(n,6) END;
WHILE x< 1 DO x:=x*10; DEC(n) END;
WHILE x>=10 DO x:=x/10; INC(n) END;
IF x<1 THEN x:=1 END;
END Norm;
PROCEDURE DeleteSpaces*(VAR str:ARRAY OF CHAR);
VAR
s,d:INTEGER;
BEGIN
s:=0; d:=0;
WHILE (s<LEN(str)) AND (str[s]#0X) DO
IF str[s]#Space THEN
str[d]:=str[s];
INC(d)
END;
INC(s);
END;
IF d<LEN(str) THEN str[d]:=0X END;
END DeleteSpaces;
PROCEDURE RealToString*(x:Real;
VAR str:ARRAY OF CHAR;
gs,nks:INTEGER;expo,left:BOOLEAN):BOOLEAN;
VAR
pos,oldgs,vks,e,len:INTEGER;
oldx:Real;
xneg:BOOLEAN;
PROCEDURE Put(c:CHAR);
BEGIN
IF pos<LEN(str) THEN str[pos]:=c; INC(pos) END
END Put;
PROCEDURE Format;
BEGIN
IF e>=gs THEN expo:=TRUE END;
IF expo OR (e<0) THEN
vks:=1;
ELSE
vks:=e+1
END;
IF (gs>vks+nks) THEN gs:=vks+nks END;
IF NOT expo AND (e<0) THEN x:=oldx END;
END Format;
BEGIN
xneg:=x<0;
x:=ABS(x);
oldx:=x;
oldgs:=gs;
Norm(x,e);
Format;
x:=x+5/Pow10(gs);
IF x>=10 THEN
x:=x/10;
IF x<1 THEN x:=1 END;
INC(e);
gs:=oldgs;
Format;
END;
len:=gs+1;
IF expo THEN INC(len,ExpSize) END;
IF nks>0 THEN INC(len) END;
IF len>LEN(str) THEN RETURN FALSE END;
pos:=0;
IF NOT left THEN
WHILE pos<(LEN(str)-len) DO Put(Space) END;
END;
IF xneg THEN Put(Minus) ELSE Put(Space) END;
WHILE gs>0 DO
IF vks=0 THEN Put(Point) END;
DEC(vks);
DEC(gs);
Put(Digit[ENTIER(x) MOD 10]);
IF x>TenE8 THEN x:=x-MathLib0.Floor(x) END;
x:=x*10;
END;
IF expo THEN
Put(Exponent);
IF e<0 THEN
Put(Minus);
e:=-e;
ELSE
Put(Plus)
END;
(* $IF LONGREAL *)
Put(Digit[e DIV 100]);
e:=e MOD 100;
(* $END *)
Put(Digit[e DIV 10]);
Put(Digit[e MOD 10]);
END;
Put(Nul);
RETURN TRUE;
END RealToString;
PROCEDURE StringToReal*(str:ARRAY OF CHAR;VAR x:Real):BOOLEAN;
VAR
pos,e:INTEGER;
neg,expoNeg:BOOLEAN;
pow:Real;
c:CHAR;
PROCEDURE Next;
BEGIN
INC(pos);
IF pos<LEN(str) THEN c:=str[pos] ELSE c:=0X END;
END Next;
PROCEDURE Negative():BOOLEAN;
BEGIN
CASE c OF '-':Next; RETURN TRUE|
'+':Next
ELSE END;
RETURN FALSE
END Negative;
PROCEDURE ReadReal;
VAR
pow:Real;
neg:BOOLEAN;
start,pointPos,p:INTEGER;
BEGIN
x:=0;
neg:=Negative();
start:=pos;
pow:=1;
pointPos:=MAX(INTEGER);
WHILE (c>='0') AND (c<='9') DO Next END;
IF c=Point THEN pointPos:=pos; Next END;
WHILE (c>='0') AND (c<='9') DO Next END;
p:=pos-1;
WHILE p>pointPos DO
x:=(x+(ORD(str[p])-ORD('0')))/10;
DEC(p)
END;
IF (p>=0) AND (str[p]=Point) THEN DEC(p) END;
WHILE p>=start DO
x:=x+pow*(ORD(str[p])-ORD('0'));
pow:=pow*10;
DEC(p);
END;
IF neg THEN x:=-x END;
END ReadReal;
BEGIN
pos:=-1;
Next;
ReadReal;
IF (x=MaxReal) OR (x=MinReal) THEN RETURN FALSE END;
IF (c='e') OR (c='E') THEN
e:=0;
Next;
expoNeg:=Negative();
WHILE (e<=1000) AND (c>='0') AND (c<='9') DO
e:=e*10+(ORD(c)-ORD('0'));
Next;
END;
pow:=Pow10(e);
IF (pow=MaxReal) OR (pow=MinReal) THEN RETURN FALSE END;
IF expoNeg THEN
x:=x/pow
ELSE
x:=x*pow
END
END;
RETURN (c=0X) AND (x#MaxReal) AND (x#MinReal)
END StringToReal;
(* $IF LONGREAL *)
END LongRealConversions2.
(* $ELSE *)
END RealConversions2.
(* $END *)